package com.wewins.fota.bean.bo.cond;

import com.alibaba.fastjson.JSONObject;
import com.wewins.fota.bean.dto.CheckStatusReq;
import com.wewins.fota.common.constant.CommonConst;
import com.wewins.fota.common.util.CommonUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;

@Data
@Slf4j
@Builder
@AllArgsConstructor
public class PlanCond implements Cond {
    private String imei;

    private int type;

    private int updateType;

    private List<Long> timeRange;

    private String otherSrcCond;

    private String otherDstCond;

    @Override
    public boolean check(Object obj) {
        if (!(obj instanceof CheckStatusReq)) {
            return false;
        }
        CheckStatusReq cond = (CheckStatusReq) obj;
        if (!cond.isDev() && type == CommonConst.PLAN_TYPE_TEST) {
            return false;
        }
        // update type
        if (updateType != CommonConst.FOTA_UPDATE_TYPE_ALL && updateType != cond.getAuto()) {
            return false;
        }
        // imei check
        if (!StringCond.parse(this.imei).check(cond.getImei())) {
            return false;
        }

        // time check
        if (!isValid4Time()) {
            return false;
        }

        return isValidOtherCond(this.otherSrcCond, cond.getOthers());
    }

    /**
     * 非必填字段，以用户调用api的参数为准，不传则默认通过校验；
     * src条件：升级计划中单个tag与版本tag之间的关系是：多对一
     * dst条件：升级计划中单个tag与版本tag之间的关系是：一对一
     * 因此根据字符条件模型关系，通过升级计划的cond 来check版本的cond
     * @param compareCond api传入的用户参数
     */
    private boolean isValidOtherCond(String baseCondStr, Map<String, String> compareCond) {
        Map<?, ?> baseCond = JSONObject.parseObject(baseCondStr, Map.class);
        if (CommonUtil.isEmptyMap(baseCond) && CommonUtil.isEmptyMap(compareCond)) {
            return true;
        }

        if ((CommonUtil.isEmptyMap(baseCond) || CommonUtil.isEmptyMap(compareCond)) || compareCond.size() != baseCond.size()) {
            return false;
        }
        for (Map.Entry<String, String> item : compareCond.entrySet()) {
            String cond = (String) baseCond.get(item.getKey());
            if (cond == null) {
                return false;
            }
            if (!StringCond.parse(cond).check(item.getValue())) {
                return false;
            }
        }
        return true;
    }

    private boolean isValid4Time() {
        if (timeRange == null || timeRange.size() == 0) {
            return true;
        }
        if (timeRange.size() != 2) {
            log.warn("the timeRange of some plan may be exception???? -> " + timeRange);
            return false;
        }
        long curDate = System.currentTimeMillis();
        long minDate = timeRange.get(0);
        long maxDate = timeRange.get(1);
        if (CommonUtil.compareInnerDay(minDate, maxDate) == -1) {  // 最小值 小于 最大值
//            当前值不比最小值小 并且 当前值不比最大值大
            return CommonUtil.compareInnerDay(curDate, minDate) != -1 && CommonUtil.compareInnerDay(curDate, maxDate) != 1;
        } else { // 最小值 不小于 最大值
//            当前值不比最小值小 或者 当前值不比最大值大
            return CommonUtil.compareInnerDay(curDate, minDate) != -1 || CommonUtil.compareInnerDay(curDate, maxDate) != 1;
        }
    }

    /**
     * 目标版本的flag标记过滤
     * 升级计划中目标版本的flag条件应该 完全匹配 版本管理中版本的flag条件；
     *
     * @param flagMap redis中符合srcCond条件的版本对应的flag字段集合
     */
    public boolean accept(Map<String, String> flagMap) {
        return isValidOtherCond(this.otherDstCond, flagMap);
    }
}
